﻿using Core.Domain.Catalog;
using Services.Stores;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Services.Catelog
{

    /// <summary>
    /// 类别扩展
    /// </summary>
    public static class CategoryExtensions
    {
        public static IList<Category> SortCategoriesForTree(this IList<Category> source, int parentId = 0, bool ignoreCategoriesWithoutExistingParent = false)
        {
            if (source == null)
                throw new ArgumentNullException("source");

            var result = new List<Category>();

            foreach (var cat in source.ToList().FindAll(c => c.ParentId == parentId))
            {
                result.Add(cat);
                result.AddRange(SortCategoriesForTree(source, cat.Id, true));
            }
            if (!ignoreCategoriesWithoutExistingParent && result.Count != source.Count)
            {
                foreach (var cat in source)
                    if (result.FirstOrDefault(x => x.Id == cat.Id) == null)
                        result.Add(cat);
            }
            return result;
        }


        /// <summary>
        /// 获取格式化
        /// </summary>
        public static string GetFormattedBreadCrumb(this Category category,
            ICategoryService categoryService,
            string separator = ">>")
        {
            if (category == null)
                throw new ArgumentNullException("category");

            string result = string.Empty;

            var alreadyProcessedCategoryIds = new List<int>() { };

            while (category != null && 
                !category.Deleted &&
                !alreadyProcessedCategoryIds.Contains(category.Id))
            {
                if (String.IsNullOrEmpty(result))
                {
                    result = category.Name;
                }
                else
                {
                    result = string.Format("{0} {1} {2}", category.Name, separator, result);
                }

                alreadyProcessedCategoryIds.Add(category.Id);

                category = categoryService.GetCategoryById(category.ParentId);

            }
            return result;
        }

        /// <summary>
        /// 格式化
        /// </summary>
        public static string GetFormattedBreadCrumb(this Category category,
            IList<Category> allCategories,
            string separator = ">>")
        {
            if (category == null)
                throw new ArgumentNullException("category");

            if (allCategories == null)
                throw new ArgumentNullException("category");

            string result = string.Empty;

            var alreadyProcessedCategoryIds = new List<int>() { };

            while (category != null &&  
                   !category.Deleted && 
                   !alreadyProcessedCategoryIds.Contains(category.Id)) //prevent circular references 
            {
                if (String.IsNullOrEmpty(result))
                {
                    result = category.Name;
                }
                else
                {
                    result = string.Format("{0} {1} {2}", category.Name, separator, result);
                }

                alreadyProcessedCategoryIds.Add(category.Id);

                category = (from c in allCategories
                            where c.Id == category.ParentId
                            select c).FirstOrDefault();
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        public static IList<Category> GetCategoryBreadCrumb(this Category category,
            ICategoryService categoryService,
            IStoreMappingService storeMappingService,
            bool showHidden = false)
        {
            if (category == null)
                throw new ArgumentNullException("category");

            var result = new List<Category>();

            //used to prevent circular references
            var alreadyProcessedCategoryIds = new List<int>() { };

            while (category != null && 
                !category.Deleted &&
                (showHidden || storeMappingService.Authorize(category)) &&
                !alreadyProcessedCategoryIds.Contains(category.Id)) 
            {
                result.Add(category);

                alreadyProcessedCategoryIds.Add(category.Id);

                category = categoryService.GetCategoryById(category.ParentId);
            }
            result.Reverse();
            return result;
        }

    }
}
